#ifndef AI_H
#define AI_H

#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>

using namespace std;

#define MAP_SIZE 15
#define WIN_LEN 5
#define BUDGET 40000
#define BLACK 1
#define WHITE -1
#define EMPTY 0
#define HIDDEN 30
#define FEATURE 225
#define OUTPUT 225

#include <QWidget>

typedef struct node
{
    //该节点父节点
    node *parent;
    //坐标位置
    int x;
    int y;
    //下一手颜色
    int nextColor;
    //该节点收益
    int reward;
    //该节点被访问次数
    int visNum;
    //棋盘
    int map[MAP_SIZE * MAP_SIZE];
    //该节点可行的下一步
    vector<node *> nextAddr;
    vector<int> nextPos;
    node()
    {
        parent = NULL;
        reward = 0;
        visNum = 0;
        x = -1;
        y = -1;
        nextAddr.clear();
        nextPos.clear();
    }
    node(node *root, int X, int Y)
    {
        parent = root;
        reward = 0;
        visNum = 0;
        x = X;
        y = Y;
        nextAddr.clear();
        nextPos.clear();
    }
} Node;


class AI : public QObject
{

    Q_OBJECT
signals:
    void sendPredict(int x, int y);

public slots:
    void setRoot(int* map, bool this_color, int prev_x, int prev_y);

public:

    AI();
    ~AI();

    void MCTS();
    void deleteTree(Node *root);
    void backPropagation(Node *node, int reward);
    int defaultPolicy(Node *root);
    Node *treePolicy(Node *root);
    Node *expand(Node *root, int x, int y);
    Node *bestChild(Node *root, double Constant);
private:
    Node* rootNode;
    bool win;
    double v[HIDDEN][FEATURE];
    double w[OUTPUT][HIDDEN];
    double v_b[HIDDEN];
    double w_b[OUTPUT];
    double _out[HIDDEN];
    double t_out[OUTPUT];

    int getResult(Node *root);
    void copy(Node *src, Node *aim);
    int indexOf(Node *root, int index);
    void copy(int src[], int aim[]);
    void paraUpload();
    void setProbability(int in[]);
    double getProbability(int x, int y);
    bool subDiagonal(int map[], int x, int y);
    bool mainDiagonal(int map[], int x, int y);
    bool colJudge(int map[], int x, int y);
    bool rowJudge(int map[], int x, int y);
    bool drawJudge(int map[]);
    bool isTerminal(Node *root);
};


#endif // AI_H
